/**
 * Alipay.com Inc.
 * Copyright (c) 2004-2016 All Rights Reserved.
 */
package com.alipay.study.core.security.config;

import java.util.Arrays;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import com.alipay.study.common.contact.security.SecurityWebContact;

/**
 * 
 * @author wb-qlj205528
 * @version $Id: WebSpringSecurityConfig.java, v 0.1 2016年11月10日 下午12:40:08 wb-qlj205528 Exp $
 */
@EnableWebSecurity
public class WebSpringSecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 登录成功处理的handler
     */
    @Autowired
    private AuthenticationSuccessHandler loginSuccessHandler;

    /**
     * 登录失败处理的handler
     */
    @Autowired
    private AuthenticationFailureHandler loginFailHandler;

    /**
     * 退出成功处理的handler
     */
    @Autowired
    private LogoutSuccessHandler         logOutSuccessHandler;

    /**
     * 退出过程中的handler
     */
    @Autowired
    private LogoutHandler                louOutHandler;
    /***
     * security contact
     */
    @Autowired
    private SecurityWebContact           securityWebContact;

    /** 
     * @see org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#configure(org.springframework.security.config.annotation.web.builders.HttpSecurity)
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
        /**
         * 指定不加入权限控制的url
         */
        .antMatchers(securityWebContact.getExcuteMatchers()).permitAll()
        /**
         * 指定默认的权限
         */
        .anyRequest().hasAnyRole(securityWebContact.getDefaultRole()).and()
        /**
         * 指定登录相关配置
         */
        .formLogin().loginPage(securityWebContact.getLoginPage())
            .usernameParameter(securityWebContact.getUsernameParam())
            .passwordParameter(securityWebContact.getPasswordParam())
            /**
             * 指定登录的url,不指定默认为/login
             */
            .loginProcessingUrl(securityWebContact.getLoginProcessingUrl())
            /**
             * 这是默认的登录成功地址，当用户没有访问其他url，从登录页面的登录成功之后跳转的地址
             */
            .defaultSuccessUrl(securityWebContact.getDefaultSuccessUrl())
            /**
             * 自定义handler,登录成功之后如何进行页面跳转,默认配置失效
             */
            .successHandler(loginSuccessHandler)
            .failureHandler(loginFailHandler)
            /**
             * 每次登陆成功之后都重定向到此地址
             */
            .and()
            .logout()
            .logoutUrl(securityWebContact.getLogoutUrl())
            .addLogoutHandler(louOutHandler)
            .logoutSuccessHandler(logOutSuccessHandler)
            .logoutSuccessUrl(securityWebContact.getLogoutSuccessUrl())

            .and()
            //csrf
            .csrf()
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            .and()
            //cors
            .cors()
            /**
             * header相关配置
             */
            .and()
            .headers()
            //Cache-Control
            .defaultsDisabled()
            .cacheControl()
            .and()
            // Public-Key-Pins-Report-Only 
            .httpPublicKeyPinning().includeSubDomains(true)
            .reportUri(securityWebContact.getPublicKeyPinningReportUrl())
            .addSha256Pins(securityWebContact.getPublicKeyPinningSha256Pins())
            .reportOnly(securityWebContact.getPublicKeyPinningReportOnly())
            //
            .and()
            //X-Content-Type-Options: nosniff   
            .contentTypeOptions()
            //
            .and()
            //X-Frame-Options: SAMEORIGIN 
            .frameOptions().sameOrigin()
            // Content-Security-Policy-Report-Only
            .contentSecurityPolicy(securityWebContact.getContentSecurityPolicy()).reportOnly()
            .and()
            //X-XSS-Protection: 1; mode=block
            .xssProtection().block(true).and()
            //https
            .httpStrictTransportSecurity().includeSubDomains(true).maxAgeInSeconds(31536000);
    }

    /**
     * cors配置
     * 
     * @return
     */
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        /**
         * 设置允许来自哪些域名的ajax跨域调用
         */
        configuration.setAllowedOrigins(Arrays.asList(securityWebContact.getAllowedOrigins()));
        /**
         * 设置允许哪几种请求方式可以跨域访问
         */
        configuration.setAllowedMethods(Arrays.asList(securityWebContact.getAllowedMethod()));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        /**
         * 指定configuration设置的作用范围
         */
        source.registerCorsConfiguration(securityWebContact.getCorsConfigurationRoot(),
            configuration);
        return source;
    }
}
